/****************************************************************************
*                                                                           *
* IocpServer.h -- socket completion port class                              *
*                                                                           *
* Copyright (c) 2013 by cooling.和谐掉QQ 防止社工牛 All rights reserved.              *
*                                                                           *
****************************************************************************/
 
#pragma once
#include <WinSock2.h>
#include <MSTcpIP.h>
#include <MSWSock.h>
#include <process.h>
#pragma comment(lib, "ws2_32.lib")
 
#define  hot_size 1024
#define  buf_size 4096
#define  unm_size 8192
//////////////////////////////////////////////////////////////////////////
typedef enum _tagIOTYPE
{
    init_flag,
    aept_flag, // AcceptEx
    recv_flag,
    send_flag,
    exit_flag
}IOTYPE, *LP_IOTYPE;
 
typedef struct _PER_SOCKET_CONTEXT
{
    SOCKET        sClientSocket;
    bool          bMainSocket;
    CHAR          szIpString[16];
    unsigned long ulIpAddress;
    unsigned long ulDialog[2];
 
    _PER_SOCKET_CONTEXT()
    {
        ulIpAddress   = 0;
        bMainSocket   = false;
        sClientSocket = INVALID_SOCKET;
        memset(szIpString,0,sizeof(szIpString));
        memset(ulDialog,0,sizeof(ulDialog));
    }
}PER_SOCKET_CONTEXT, *LP_PER_SOCKET_CONTEXT;
 
typedef struct _PER_IO_OPENATION_DATA
{
    OVERLAPPED   Overlapped;
    WSABUF       WsaBuf;
    CHAR         BitBuf[buf_size];
    IOTYPE       IoTYPE;
    SOCKET       sAcceptSocket;
 
    _PER_IO_OPENATION_DATA()
    {
        WsaBuf.buf = BitBuf;
        WsaBuf.len = buf_size;
        IoTYPE     = init_flag;
        memset(BitBuf,0,buf_size);
        memset(&Overlapped,0,sizeof(OVERLAPPED));
    }
 
}PER_IO_OPENATION_DATA, *LP_PER_IO_OPENATION_DATA;
 
// define callback Function
typedef void __stdcall NOTIFYPROC(LP_PER_SOCKET_CONTEXT, PCHAR, ULONG, LPVOID, UINT);
 
class CIocpServer
{
public:
    CIocpServer(void);
    ~CIocpServer(void);
 
public:
 
    bool             Start(NOTIFYPROC *pNotifyProc, void *lpContext, u_short uPort);
    bool             Shutdown();
    bool             DisConnect(SOCKET sclient);
    bool             SendMsg(SOCKET sclient, char* data, u_long ulDataLength, bool bflag = true);
 
protected:
 
    bool             _InitIOCPServer(unsigned short uPort);
    bool             _RunAcceptEx(LP_PER_IO_OPENATION_DATA lpPerIoData = NULL);
    bool             _PostAcceptEx(LP_PER_SOCKET_CONTEXT lpPerStContext = NULL);
    bool             _PostRecvData(LP_PER_SOCKET_CONTEXT lpPerStContext = NULL, LP_PER_IO_OPENATION_DATA lpPerIoData = NULL);
    bool             _RetvalSocketPool(LP_PER_SOCKET_CONTEXT lpPerStContext = NULL, LP_PER_IO_OPENATION_DATA lpPerIoData = NULL, bool bflag = false);
    bool             _DestroySocketPool();
 
    HANDLE           _BindCreateIoCompletionPort(SOCKET hSocket, HANDLE hCompletionPort, ULONG_PTR lpStContext, DWORD dwNumber = 0);
    unsigned int     _GetMswSockFuntion(SOCKET s, GUID &guid, void* &lp);
    unsigned int     _GetProcessOfNumber();
 
private:
 
    bool             m_bStatus;
    DWORD            m_dwFlags;
    DWORD            m_dwSockLen;
    LPVOID           m_lpContext[2];
      
    HANDLE           m_hWorkEvent;
    HANDLE           m_hCompletionPort;
    SOCKET           m_sListenSocket;
    SOCKET           m_uSocketPool[SHRT_MAX]; // socket disconnectex pool /*unsigned int type
    unsigned int     m_uThreads;
    unsigned int     m_uThreadId;
    CRITICAL_SECTION cIocpSection;
 
    NOTIFYPROC        *m_lpNotifyProc;
    LPFN_ACCEPTEX      m_lpfnAcceptEx;
    LPFN_DISCONNECTEX  m_lpfnDisconnectEx;
 
    friend unsigned __stdcall _CheckMemory(void *lpContext);
    friend unsigned __stdcall _WorkerThread(void *lpContext);
    CMap <SOCKET,SOCKET,LP_PER_SOCKET_CONTEXT,LP_PER_SOCKET_CONTEXT&> mapStContext;
};